﻿#include "CMOSSpectroMeter.h"
#include <QDebug>
#include "qstringutils.h"

CMOSSpectroMeter::CMOSSpectroMeter():m_hDevice(0)
{

}

CMOSSpectroMeter::~CMOSSpectroMeter()
{
    CloseSpectro();
}

void CMOSSpectroMeter::SetOtherConfig(QJsonObject config)
{
    _measParam.integrationTime=config["IntegrationTime"].toDouble();
    _measParam.integrationDelay=config["IntegrationDelay"].toDouble();
    _measParam.NrAverages=config["AverageTimes"].toInt();
    // 非同步模式下TriggerMode、TriggerSourced都为0 同步模式下需要选择一个主设备,主设备的m_Mode为0
    _measParam.triggerMode=0;
    _measParam.triggerSource=0;

    _serial=config["Serial"].toString();
}

QMap<int,CMOSSpectroMeter*> CMOSSpectroMeter::_meterMap;

bool CMOSSpectroMeter::InitComm()
{
    int iRtn = AVS_Init(-1);    //USB或eth网
    return iRtn>0;
}

bool CMOSSpectroMeter::EnumSpectro(QList<AvsInfo> &listAvsInfo)
{
    bool isSuccessed = true;
    int deviceCount=AVS_Init(-1);
    if(deviceCount==0)
    {
        return true;
    }
    unsigned int RequiredSize = 0;
    AVS_UpdateETHDevices(0, &RequiredSize, NULL);
    char *DiscoveredDevs = new char[RequiredSize];
    BroadcastAnswerType *DeviceList = (BroadcastAnswerType*)DiscoveredDevs;
    int iDeviceNum = AVS_UpdateETHDevices(RequiredSize,&RequiredSize,DeviceList);
    if(iDeviceNum > 0) {//获取设备列表信息
        AVS_GetList(0, &RequiredSize, NULL );
        char *FoundDevices = new char[RequiredSize];
        AvsIdentityType *DeviceList = (AvsIdentityType*)FoundDevices;
        iDeviceNum = AVS_GetList(RequiredSize,&RequiredSize, DeviceList);

        for(int i = 0;(iDeviceNum > 0)&&(i < iDeviceNum); i++) {
            //先对数据进行清空，以免造成累加
            AvsInfo sTempDeviceInfo = AvsInfo();
            for(int j = 0; j < AVS_SERIAL_LEN; j++) {//设备名
                if(DeviceList[i].SerialNumber[j]=='\0')
                {
                    break;
                }
               sTempDeviceInfo.serial += DeviceList[i].SerialNumber[j];
            }
            for(int j = 0; j < USER_ID_LEN; j++) { //设备用户友好名称
               sTempDeviceInfo.friendname += DeviceList[i].UserFriendlyName[j];
            }
            sTempDeviceInfo.status = DeviceList[i].Status;
            qDebug()<<__FUNCTION__<<__LINE__<<DeviceList[i].Status;
            listAvsInfo.append(sTempDeviceInfo);//更新到输出listAvsInfo
        }
        isSuccessed = true;
        qDebug()<<__FUNCTION__<<__LINE__<<iDeviceNum<<listAvsInfo.first().serial;
    } else {
        AVS_Done();
        isSuccessed = false;
    }
    return isSuccessed;
}

bool CMOSSpectroMeter::OpenSpectro()
{
    qDebug()<<__FUNCTION__<<__LINE__;
    AvsIdentityType avsActive;
    QStringUtils::QStringCpoyCStrArray(_serial,avsActive.SerialNumber,AVS_SERIAL_LEN);
//    InitComm();;

    m_hDevice = AVS_Activate(&avsActive);
    if(m_hDevice != INVALID_AVS_HANDLE_VALUE)
    {
        GetLambda();
        CMOSSpectroMeter::_meterMap.insert(m_hDevice,this);
        return true;
    }
    else
    {
        qDebug()<<__FUNCTION__<<__LINE__<< "Opening device failed!";
        return false;
    }
}

bool CMOSSpectroMeter::CloseSpectro()
{
//    AVS_ResetDevice(m_hDevice);
    return AVS_Deactivate(m_hDevice);
}

bool CMOSSpectroMeter::SetMeasureParam(AvsMeasPara param)
{
    memcpy(&_measParam, &param, sizeof(AvsMeasPara));
    unsigned int needSize = 0;
    unsigned int bufferSize = sizeof(DeviceConfigType);
    DeviceConfigType *ps =  (DeviceConfigType*)new char[sizeof(DeviceConfigType)];
    //获取数据
    AVS_GetParameter(m_hDevice, bufferSize, &needSize, ps);
    ps->m_Detector.m_Gain[0]=_measParam.gain[0];
    ps->m_Detector.m_Gain[1]=_measParam.gain[1];
    ps->m_StandAlone.m_Meas.m_IntegrationTime=_measParam.integrationTime;
    ps->m_StandAlone.m_Meas.m_IntegrationDelay=_measParam.integrationDelay;
    ps->m_StandAlone.m_Meas.m_NrAverages=_measParam.NrAverages;
    ps->m_StandAlone.m_Meas.m_Trigger.m_Mode=_measParam.triggerMode;
    ps->m_StandAlone.m_Meas.m_Trigger.m_Source=_measParam.triggerSource;
    delete _avsMeasConfig;
    _avsMeasConfig=ps;
    SetMaster(_measParam.isMasterChannel);
    if(AVS_SetParameter(m_hDevice,_avsMeasConfig)==0)
    {
        return true;
    }
    else
    {
        qDebug()<<__FUNCTION__<<__LINE__<<m_hDevice<<"光谱仪参数设置失败!";
        return false;
    }
}

bool CMOSSpectroMeter::GetMeasParam(AvsMeasPara &measConfigParam)
{
    unsigned int needSize = 0;
    unsigned int bufferSize = sizeof(DeviceConfigType);
    DeviceConfigType *psDeviceData =(DeviceConfigType*)new char[sizeof(DeviceConfigType)];
    //获取数据
    AVS_GetParameter(m_hDevice, bufferSize, &needSize, psDeviceData);
    MeasConfigType psMeasConfig = psDeviceData->m_StandAlone.m_Meas;
    _measParam.integrationDelay=psMeasConfig.m_IntegrationDelay;
    _measParam.integrationTime=psMeasConfig.m_IntegrationTime;
    _measParam.NrAverages=psMeasConfig.m_NrAverages;
    _measParam.triggerMode=psMeasConfig.m_Trigger.m_Mode;
    _measParam.triggerSource=psMeasConfig.m_Trigger.m_Source;
    _measParam.gain[0]=psDeviceData->m_Detector.m_Gain[0];
    _measParam.gain[1]=psDeviceData->m_Detector.m_Gain[1];
    measConfigParam=_measParam;
    if(_avsMeasConfig!=nullptr)
    {
        delete [] _avsMeasConfig;
    }
    _avsMeasConfig=psDeviceData;
    return true;
}

const QList<double> CMOSSpectroMeter::GetLambda()
{
    if(_lambda.empty())
    {
        unsigned short NumPixels;
        AVS_GetNumPixels(m_hDevice,&NumPixels);
        double *dLambda=new double[NumPixels];
        AVS_GetLambda(m_hDevice, dLambda);
        for(int i=0;i<NumPixels;i++)
        {
            _lambda.append(dLambda[i]);
        }
    }
    return _lambda;
}

void CMOSSpectroMeter::SetMaster(bool isMaster)
{
    int ret=isMaster?AVS_SetSyncMode(m_hDevice,1):AVS_SetSyncMode(m_hDevice,0);
    if(ret!=0)
    {
        throw _serial+QString("设置%1失败").arg(isMaster?"master":"slaver");
    }
}

bool CMOSSpectroMeter::StartMeasure()
{
    Stop();
    AvsMeasPara para;
    GetMeasParam(para);
    MeasConfigType l_PrepareMeasData=_avsMeasConfig->m_StandAlone.m_Meas;
    QLocale::setDefault(QLocale::Dutch);
    //使用高亮度通道
    AVS_UseHighResAdc(m_hDevice,true);
//    qDebug()<<__FUNCTION__<<__LINE__<<_serial<<"Source:"<<_avsMeasConfig->m_StandAlone.m_Meas.m_Trigger.m_Source
//           <<"Mode:"<<_avsMeasConfig->m_StandAlone.m_Meas.m_Trigger.m_Mode;
    AVS_PrepareMeasure(m_hDevice,&l_PrepareMeasData);
    AVS_MeasureCallback(m_hDevice, &CMOSSpectroMeter::callback, 1);
    return true;
}

bool CMOSSpectroMeter::Stop()
{
    return AVS_StopMeasure(m_hDevice)==0;
}

void CMOSSpectroMeter::ReceiveDataIsHere(int result, int device)
{
    //这两步非常重要,线程同步工具
    static QMutex _mutex;
    QMutexLocker locker(&_mutex);
//    qDebug()<<__FUNCTION__<<__LINE__<<device;
    if (result >= ERR_SUCCESS&&device==m_hDevice)
    {
        QList<QPointF> ret;
        double *pSpectrum = new double[_lambda.count()];
        unsigned int time = 0;
        if(ERR_SUCCESS == AVS_GetScopeData(m_hDevice, &time, pSpectrum))
        {
            for(int i = 0; i < _lambda.count(); i++) {
                int intensity = pSpectrum[i];   //强度转为整数存储
                ret.append(QPointF(_lambda.at(i),intensity));
            }
            AvsMeasResult sendData;
            sendData.SerialId=_serial;
            sendData.resultData=ret;
            emit OnDataReceive(sendData);
        }
    }
}

void CMOSSpectroMeter::callback(AvsHandle *handle, int *result)
{
    CMOSSpectroMeter::_meterMap[*handle]->ReceiveDataIsHere(*result,*handle);
}

SpectroInfoTag CMOSSpectroMeter::GetSpectrumInfo()
{
//    qDebug()<<__FUNCTION__<<__LINE__<<GetLambda().count();
    SpectroInfoTag ret(GetLambda());
    ret.serilID=_serial;
    return ret;
}
